﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LotteryVote.Entity;
using LotteryVote.Data;
using LotteryVote.Utility;
using LotteryVote.Logic.Application;
using LotteryVote.Logic.Exceptions;

namespace LotteryVote.Logic.Limit
{
    internal class UserLimiter : ILimitCheck
    {
        private BetOrderDataAccess _daBetOrder;
        internal BetOrderDataAccess DaBetOrder
        {
            get
            {
                if (_daBetOrder == null)
                    _daBetOrder = new BetOrderDataAccess();
                return _daBetOrder;
            }
            set
            {
                _daBetOrder = value;
            }
        }

        private BetLimitFacade _blBetlimit;
        public BetLimitFacade BlBetLimit
        {
            get
            {
                if (_blBetlimit == null)
                    _blBetlimit = new BetLimitFacade();
                return _blBetlimit;
            }
            set
            {
                _blBetlimit = value;
            }
        }

        private IDictionary<int, IList<BetOrder>> _betOrders;
        protected IDictionary<int, IList<BetOrder>> BetOrderDic
        {
            get
            {
                if (_betOrders == null)
                    _betOrders = new Dictionary<int, IList<BetOrder>>();
                return _betOrders;
            }
        }

        private IDictionary<int, IList<BetLimit>> _betLimits;
        protected IDictionary<int, IList<BetLimit>> BetLimitDic
        {
            get
            {
                if (_betLimits == null)
                    _betLimits = new Dictionary<int, IList<BetLimit>>();
                return _betLimits;
            }
        }

        private IDictionary<int, IList<GameBetLimit>> _gameBetLimits;
        protected IDictionary<int, IList<GameBetLimit>> GameBetLimitDic
        {
            get
            {
                if (_gameBetLimits == null)
                    _gameBetLimits = new Dictionary<int, IList<GameBetLimit>>();
                return _gameBetLimits;
            }
        }

        public string ErrorMessage { get; private set; }
        public bool Inject(BetOrder order)
        {
            var orderList = GetOrderByUser(order.UserId);
            return CheckBetLimit(order, orderList) && CheckGameLimit(order, orderList);
        }

        protected IList<BetOrder> GetOrderByUser(int userId)
        {
            if (!BetOrderDic.ContainsKey(userId))
                BetOrderDic.Add(userId, DaBetOrder.ListOrder(userId, BetStatus.Valid, DateTime.Today));
            return BetOrderDic[userId];
        }
        protected IList<BetLimit> GetLimitByUser(int userId)
        {
            if (!BetLimitDic.ContainsKey(userId))
                BetLimitDic.Add(userId, BlBetLimit.ListLimitByUser(userId));
            return BetLimitDic[userId];
        }
        protected IList<GameBetLimit> GetGameLimitByUser(int userId)
        {
            if (!GameBetLimitDic.ContainsKey(userId))
                GameBetLimitDic.Add(userId, BlBetLimit.ListGameLimitByUser(userId));
            return GameBetLimitDic[userId];
        }
        /// <summary>
        /// Checks the bet limit.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <param name="orderList">The order list.</param>
        /// <returns></returns>
        protected bool CheckBetLimit(BetOrder order, IList<BetOrder> orderList)
        {
            var gameplayway = LotterySystem.Current.GamePlayWay.Find(it => it.Id == order.GamePlayWayId);
            var betLimitList = GetLimitByUser(order.UserId);
            var betlimit = betLimitList.Find(it => it.GameId == gameplayway.GameType.GameId);   //找出单注限制
            if (order.Amount < betlimit.LeastLimit || order.Amount > betlimit.LargestLimit)
                return false;
            else
                return true;
        }
        protected bool CheckGameLimit(BetOrder order, IList<BetOrder> orderList)
        {
            //注单中的公司肯定在今日开奖公司中
            var company = TodayLotteryCompany.Instance.GetTodayCompany().Find(it => it.CompanyId == order.CompanyId);
            if (company == null) return false;
            var companyType = (CompanyType)company.CompanyType.Id;
            //根据长度来识别游戏类型
            var gameTypeOrder = orderList.Where(it => it.Num.Length == order.Num.Length);
            var totalAmount = gameTypeOrder.Sum(it => it.Amount);   //取得总金额
            totalAmount += order.Amount;
            var gameLimitList = GetGameLimitByUser(order.UserId);
            //找出游戏限制
            var gameLimit = gameLimitList.Find(it => it.CompanyType == companyType && it.GamePlayWayId == order.GamePlayWayId);
            if (gameLimit == null)
                throw new InvalidDataException(string.Format("不存在GamePlayWayId为{0}的游戏限制!", order.GamePlayWayId));

            if (totalAmount > gameLimit.LimitValue)
                return false;
            else
                orderList.Add(order);
            return true;
        }


        public void RollOrderLimit(BetOrder order)
        {
            throw new NotImplementedException();
        }
    }
}
